package com.jl.juc.atomic.atomicReferenceCAS;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 手写自旋锁案例: 使用AtomicReference原子引用实现自旋锁
 */
public class SpinkLockOfAtomicReference {

    private AtomicReference<Thread> atomicReference = new AtomicReference<>();


    public boolean lock(){
        Thread thread = Thread.currentThread();

        System.out.println(thread.getName() + "开始自旋");
        //如果原子引用中存的不是null，则自旋直到空（其他线程释放锁）
        while (!atomicReference.compareAndSet(null, thread)){

        }

        System.out.println(thread.getName() + "自旋结束，获取锁成功。");
        return true;
    }

    public boolean unLock(){
        Thread thread = Thread.currentThread();
        boolean b = atomicReference.compareAndSet(thread, null);
        System.out.println("释放锁成功。");
        return b;

    }

    public static void main(String[] args) throws InterruptedException {
        SpinkLockOfAtomicReference spinkLockDemo = new SpinkLockOfAtomicReference();

        new Thread(()->{

            try{
                spinkLockDemo.lock();
                System.out.println(Thread.currentThread().getName() + "获取到锁，开始干活。");

                System.out.println(Thread.currentThread().getName() + "开始休眠");
                TimeUnit.SECONDS.sleep(5);
                System.out.println(Thread.currentThread().getName() + "休眠结束");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                spinkLockDemo.unLock();
            }
        }, "A").start();

        //保证线程A先启动
        TimeUnit.SECONDS.sleep(2);
        System.out.println(Thread.currentThread().getName() + "开始获取锁");
        spinkLockDemo.lock();
        System.out.println(Thread.currentThread().getName() + "获取锁结束了");


    }

}
